package com.study.easyexcel.business.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.excel.util.MapUtils;
import com.study.easyexcel.api.listener.HealthMonitoring;
import com.study.easyexcel.common.exception.ExcelImportException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.List;
import java.util.Map;

/**
 * 无对象导入，通常用来接收不确定列的导入数据
 *
 * @author yuhuan
 * @date 2023/6/26
 */
public class NoModelImportListener extends HealthMonitoring<Map<Integer, String>> {

    private static final Logger logger = LoggerFactory.getLogger(NoModelImportListener.class);

    private static final int BATCH_COUNT = 5;

    private List<Map<Integer, String>> cachedList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

    private final Map<Integer, String> head = MapUtils.newHashMap();

    /**
     * 事务管理，如果涉及多表处理，可以通过编程式事务保证数据一致性
     */
    private final TransactionTemplate transactionTemplate;

    public NoModelImportListener(TransactionTemplate transactionTemplate) {
        this.transactionTemplate = transactionTemplate;
    }

    @Override
    public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
        for (Map.Entry<Integer, ReadCellData<?>> dataEntry : headMap.entrySet()) {
            Integer key = dataEntry.getKey();
            ReadCellData<?> value = dataEntry.getValue();
            head.put(key, value.getStringValue());
        }
        logger.info("解析头数据:{}", head);
    }

    @Override
    public void invoke(Map<Integer, String> dataMap, AnalysisContext analysisContext) {
        if (cachedList.size() < BATCH_COUNT) {
            this.cachedList.add(dataMap);
            return;
        }
        // 达到阈值则保存一次数据，建议执行批量插入的SQL
        logger.info("触发数据缓存阈值，执行数据持久化");
        String execute = transactionTemplate.execute((status -> {
            try {
                logger.info("数据头{}", head);
                for (Map<Integer, String> stringMap : cachedList) {
                    System.out.println(stringMap);
                }
            } catch (ExcelImportException e) {
                // 事务回滚
                status.setRollbackOnly();
                return e.getMessage();
            }
            return "";
        }));
        assert execute != null;
        if (execute.length() > 0) {
            throw new ExcelImportException(dataMap.get(0) + "导入失败，原因是：" + execute);
        }
        this.cachedList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        this.cachedList.add(dataMap);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        logger.info("数据头{}", head);
        logger.info("解析余量数据{}条", this.cachedList.size());
        for (Map<Integer, String> stringMap : cachedList) {
            System.out.println(stringMap);
        }
    }
}
